pod 是 kubernetes 中最小运行单元,默认情况下 pod 可以运行在所有工作节点上。但是默认的调度策略不能满足额外的需求,比如希望 pod 只调度某些节点;在副本数大于 1 时希望多个 pod 不要在同一个工作节点上;希望 pod 可以均匀的分布到多个工作节点等。
kubernetes pod 调度
kubernetes 默认调度器
kube-scheduler 是 kubernetes 集群中默认的调度器,在安装好 kubernetes 集群之后即可在 kube-system 命名空间下找到
kube-scheduler 发现需要创建一个 pod 时,会选择一个最佳的节点来运行新创建或者没有调度的 pod。每个 pod 有不同的要求,因此 kube-scheduler 会过滤掉不满足要求的节点。在一个集群中,可能会出现多个节点都满足要求,这些节点被称为可调度节点。如果一个集群中没有找到任何一个节点能满足 pod 的要求,那么这个 pod 会一直停留在未调度状态知道调度器可以找到合适的节点。
绕过调度器的属性: nodeName
可以通过指定 pod 资源中的 spec.nodeName
名称来绕过调度器的节点选择。
通过设置 nodeName 来指定部署的节点是很方便的,但是使用这种方式存在以下问题:
- 如果指定的节点不存在,那么 pod 不会创建
- 如果指定的节点资源不满足要求,那么 pod 不会创建。比如一个节点规格为 16 核 32G 内存,但是 pod 的 resouces.request 设置的是 20 核 30G,那么这种情况下无法创建
- 如果指定的节点掉线或者修改名称,这个情况下部署也是不稳定的
根据节点标签进行选择: nodeSelector
有的时候 pod 执行需要特定资源,比如节点上有 GPU 或者 SSD,希望 pod 可以部署到拥有这些资源的节点上。那么这时可以使用 nodeSelector。
1 | apiVersion: v1 |
为了使用 nodeSelector,需要为节点加上 label
1 | kubectl get nodes --show-labels # 查看所有节点和对应的 label |
如果 nodeSelector 指定了多个 label,那么部署的节点必须同时拥有这些 label
节点亲和性: nodeAffinity
节点亲和性功能比 nodeSelector 更强,它既可以像 nodeSelector 一样只有在满足一定标签的情况下才能调度,也可以标明一些规则不是必须,如果没有满足这些条件任然可以调度节点
节点亲和性由两种类型组成
- requiredDuringSchedulingIgnoredDuringExecution: 一种强硬的规则,只有在满足定义的条件时才能进行调度
- preferredDuringSchedulingIgnoredDuringExecution: 调度器尝试寻找满足条件的节点,如果没找到,任然会调度节点
requiredDuringSchedulingIgnoredDuringExecution
一个 requiredDuringSchedulingIgnoredDuringExecution 示例如下
1 | apiVersion: v1 |
requiredDuringSchedulingIgnoredDuringExecution 只有一个字段 nodeSelectorTerms,其下可以跟多个数组,每个数组可以是 matchExpressions
和 matchFields
两种类型。
matchExpressions
使用 label 进行筛选,matchFields
则是使用字段进行筛选。使用字段进行筛选参考 字段选择器
operator
一共有 6 种合法值,分别是 In, NotIn, Exists, DoesNotExist, Gt 和 Lt。 NodeSelectorRequirement。具体使用可以参考 操作符
preferredDuringSchedulingIgnoredDuringExecution
一个简单的 preferredDuringSchedulingIgnoredDuringExecution 示例如下
1 | apiVersion: v1 |
preferredDuringSchedulingIgnoredDuringExecution 的一个重要字段是 weight,这是一个必填字段,值在 1 到 100 之间。
当调度器找到能够满足 Pod 的其他调度请求的节点时,调度器会遍历节点满足的所有的偏好性规则, 并将对应表达式的 weight 值加和。
最终的加和值会添加到该节点的其他优先级函数的评分之上。 在调度器为 Pod 作出调度决定时,总分最高的节点的优先级也最高。
Pod 间亲和性与反亲和性
不管是 nodeName,nodeSelector 还是节点亲和性都只能选择 Pod 在哪个节点或者哪类节点上。但是如果一个 Deployoment 在有多个副本时希望尽可能让每个副本可以均匀的分布在多个可调度节点上时,以上字段就不能满足要求。此时可以考虑 Pod 间亲和性与反亲和性。